

const { ccclass, property } = cc._decorator;
// const gfx = cc['gfx'];

// const vertexFmt = new gfx.VertexFormat([
//     { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 3 },
//     { name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
//     { name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_FLOAT32, num: 4, normalize: true },
// ])
@ccclass
export default class RopeAssembler extends cc.Assembler {

    floatsPerVert = 5;

    uvOffset = 2;
    colorOffset = 4;

    public _renderData: cc.RenderData = null;
    public _local: cc.Vec2[] = [];


    vertexesCount = 0;
    // 索引个数等于 (排数-1)* 6
    indicesCount = 0;
    verticesFloats = 0;

    init(comp) {
        super.init(comp);
        this._renderData = new cc.RenderData();
        this._renderData.init(this);
        let points = comp.points;
        // 初始化索引数
        this.vertexesCount = points.length * 2;
        this.indicesCount = (points.length - 1) * 6;
        this.verticesFloats = this.floatsPerVert * (this.vertexesCount);
        this.initLocal(comp);
        this.initData(comp);
    }

    initLocal(comp) {
        this._local = [];
        this._local.length = this.vertexesCount;
    }
    initData(comp) {
        let data = this._renderData;
        data.createFlexData(0, this.verticesFloats, this.indicesCount)

        // debugger
        // console.log('indicesCount', this.indicesCount)
        // console.log('verticesFloats', this.verticesFloats)
        // console.log('vertexes', this.vertexesCount)
        // createFlexData不会填充顶点索引信息，手动补充一下
        this.initVertexes(comp);
    }
    /**初始化顶点 */
    initVertexes(sprite) {

        this.updateVerts(sprite);
        this.updateColor(sprite);
        this.updateUVs(sprite);
        this.updateIndices(sprite);
        // console.log(this._renderData.vDatas[0])
        // console.log(this._renderData.iDatas[0])
        // let ids = this._renderData.iDatas[0];
        // let vd = this._renderData.vDatas[0];
        // ids.forEach((i, idx) => {
        //     let j = this.floatsPerVert * i;
        //     let pos = cc.v2(vd[j], vd[j + 1])
        //     let wpos = sprite.node.convertToWorldSpaceAR(pos);
        //     ((i, wpos) => {
        //         sprite.scheduleOnce(() => {
        //             console.log('i', i)
        //             GameHelper.getDebugSceneCtx().strokeColor = GameHelper.rdmColor();
        //             GameHelper.drawCircle(10, wpos);
        //         }, idx * 1)
        //     })(i, wpos)
        // });
    }

    // getVfmt() {
    //     return vertexFmt;
    // }
    getBuffer() {
        //@ts-ignore
        return cc.renderer._handle._meshBuffer;
    }

    // 将准备好的顶点数据填充进 VertexBuffer 和 IndiceBuffer
    fillBuffers(comp, renderer) {
        if (renderer.worldMatDirty) {
            this.updateWorldVerts(comp);
        }

        let renderData = this._renderData;
        let vData = renderData.vDatas[0];
        let iData = renderData.iDatas[0];

        let buffer = this.getBuffer(/*renderer*/);
        let offsetInfo = buffer.request(this.vertexesCount, this.indicesCount);
        // buffer data may be realloc, need get reference after request.

        // fill vertices
        let vertexOffset = offsetInfo.byteOffset >> 2,
            vbuf = buffer._vData;

        if (vData.length + vertexOffset > vbuf.length) {
            vbuf.set(vData.subarray(0, vbuf.length - vertexOffset), vertexOffset);
        } else {
            vbuf.set(vData, vertexOffset);
        }

        // fill indices
        let ibuf = buffer._iData,
            indiceOffset = offsetInfo.indiceOffset,
            vertexId = offsetInfo.vertexOffset;             // vertexId是已经在buffer里的顶点数，也是当前顶点序号的基数
        for (let i = 0, l = iData.length; i < l; i++) {
            ibuf[indiceOffset++] = vertexId + iData[i];
        }
    }

    updateColor(comp, color = null) {
        // render data = verts = x|y|u|v|color|x|y|u|v|color|...
        // 填充render data中4个顶点的color部分
        let uintVerts = this._renderData.uintVDatas[0];
        if (!uintVerts) return;
        color = color != null ? color : comp.node.color._val;
        let floatsPerVert = this.floatsPerVert;
        let colorOffset = this.colorOffset;
        for (let i = colorOffset, l = uintVerts.length; i < l; i += floatsPerVert) {
            uintVerts[i] = color;
        }
    }

    /**渲染新的顶点数据 */
    updateRenderData(sprite) {
        if (sprite._vertsDirty) {
            this.updateVerts(sprite);
            // this.updateUVs(sprite);
            sprite._vertsDirty = false;
        }
    }
    /**更新顶点位置 */
    updateVerts(sprite) {
        if (!sprite) {
            return;
        }
        let pointList = sprite.points;
        // console.log(pointList)
        // debugger;
        let node = sprite.node,
            cw = node.width, ch = node.height;
        /******************uv计算所需参数 *************************/
        let uvs = sprite.spriteFrame.uv;
        let l = uvs[0],
            b = uvs[1],
            r = uvs[6],
            t = uvs[7]
            ;
        let uv = [l, t, r, t, r, b, l, b];
        if (sprite.spriteFrame.isRotated()) {
            uv = [r, b, r, t, l, t, l, b];
            // uv = [mx, my, l, b, l, t, r, t, r, b];
        }
        // let uv = [0.5, 0.5, 0, 1, 1, 1, 1, 0, 0, 0];

        let local = this._local;
        /******************************************************* */

        let idx = 0;
        let lastPoint = cc.v2(0, -1);
        let leftPos: cc.Vec2, rightPos: cc.Vec2;
        let width = cw;
        for (let i = 0; i < pointList.length; i++) {
            let p = pointList[i];
            let dir = lastPoint.sub(p);

            let radian = 90 * Math.PI / 180;
            leftPos = p.add(cc.v2(0, -width / 2).rotate(-radian).rotate(-Math.atan2(dir.x, dir.y)));
            rightPos = p.add(cc.v2(0, -width / 2).rotate(radian).rotate(-Math.atan2(dir.x, dir.y)));
            // leftPos = p.add(cc.v2(0, -width / 2).rotate(-radian).rotate(-Math.atan2(dir.x, dir.y)));
            // rightPos = p.add(cc.v2(0, -width / 2).rotate(radian).rotate(-Math.atan2(dir.x, dir.y)));
            local[idx++] = leftPos;
            local[idx++] = rightPos;
            lastPoint = p;
        }

        this.updateWorldVerts(sprite);
    }
    /** 更新索引 */
    updateIndices(sprite) {
        let indices = this._renderData.iDatas[0];
        let pointList = sprite.points;
        let idx = 0;
        let picSize = 2;
        for (let i = 1; i < pointList.length - 1; i++) {
            indices[idx++] = i * picSize + 0;
            indices[idx++] = i * picSize + 1;
            indices[idx++] = i * picSize + 2;

            indices[idx++] = i * picSize + 3;
            indices[idx++] = i * picSize + 1;
            indices[idx++] = i * picSize + 2;
        }
    }
    updateUVs(sprite) {
        // console.log('updateUVs');
        if (!sprite.spriteFrame) {
            return;
        }
        let cw = sprite.node.width, ch = sprite.node.height;
        let spfUVs = sprite.spriteFrame['uv']
        let l = spfUVs[0];
        let t = spfUVs[1];
        let r = spfUVs[6];
        let b = spfUVs[7];
        // if (sprite.spriteFrame.isRotated()) {
        //     l = spfUVs[5];
        //     t = spfUVs[4];
        //     r = spfUVs[3];
        //     b = spfUVs[2];
        // }
        // console.log('spfUVs', spfUVs)
        // render data = verts = x|y|u|v|color|x|y|u|v|color|...
        // 填充render data中5个顶点的uv部分
        let uvOffset = this.uvOffset;
        let floatsPerVert = this.floatsPerVert;
        let local = this._local;
        let verts = this._renderData.vDatas[0];
        for (let i = 0, idx = 0; i < local.length; i++) {
            idx = i * floatsPerVert + uvOffset;
            let p = local[i];
            let realPos = p.add(cc.v2(cw / 2, ch));
            let percentX = realPos.x / cw;
            let percentY = 1 - realPos.y / ch;
            let u = percentX * (r - l) + l;
            let v = percentY * (t - b) + b;
            // uvs[i] = cc.v2(u, v);
            verts[idx] = u;
            verts[idx + 1] = v;
            // console.log(idx, u, v, local.length)
        }
    }

    updateWorldVerts(comp) {
        if (CC_NATIVERENDERER) {
            this.updateWorldVertsNative(comp);
        } else {
            this.updateWorldVertsWebGL(comp);
        }
    }

    updateWorldVertsWebGL(comp) {
        let local = this._local;
        let verts = this._renderData.vDatas[0];

        let node = comp.node,
            cw = node.width, ch = node.height;
        // let appx = cw * (0.5 - node.anchorX);
        // let appy = ch * (0.5 - node.anchorY);

        let matrix = comp.node._worldMatrix;
        // cocos矩阵
        let matrixm = matrix.m,
            a = matrixm[0], b = matrixm[1], c = matrixm[4], d = matrixm[5],
            tx = matrixm[12], ty = matrixm[13];

        /*
        m00 = 1, m01 = 0, m02 = 0, m03 = 0,
        m04 = 0, m05 = 1, m06 = 0, m07 = 0,
        m08 = 0, m09 = 0, m10 = 1, m11 = 0,
        m12 = 0, m13 = 0, m14 = 0, m15 = 1
        */
        // [a,b,c,d] = _worldMatrix[1,2,4,5] == [1,0,0,1]
        // _worldMatrix[12,13]是xy的平移量
        // 即世界矩阵的左上角2x2是单元矩阵，说明在2D场景内没有出现旋转或者缩放
        let justTranslate = a === 1 && b === 0 && c === 0 && d === 1;
        let angle = node.angle;
        // CC_EDITOR && Editor.log('angle', angle);
        // let radian = angle * Math.PI / 180
        // 实现矩阵
        // a = Math.cos(radian) * node.scaleX;
        // b = Math.sin(radian);
        // c = -Math.sin(radian);
        // d = Math.cos(radian) * node.scaleY;
        // render data = verts = x|y|u|v|color|x|y|u|v|color|...
        // 填充render data中4个顶点的xy部分
        let index = 0;
        let floatsPerVert = this.floatsPerVert;
        for (let i = 0; i < local.length; i++) {
            let p = local[i];
            // debugger
            verts[index] = p.x * a + p.y * c + tx;
            verts[index + 1] = p.x * b + p.y * d + ty;
            index += floatsPerVert;
        }
    }

    // native场景下使用的updateWorldVerts
    // copy from \jsb-adapter-master\engine\assemblers\assembler-2d.js
    updateWorldVertsNative(comp) {
        let local = this._local;
        let verts = this._renderData.vDatas[0];
        let floatsPerVert = this.floatsPerVert;
        let node = comp.node,
            cw = node.width, ch = node.height;
        // let appx = cw * (0.5 - node.anchorX);
        // let appy = ch * (0.5 - node.anchorY);

        let index: number = 0;
        for (let i = 0; i < local.length; i++) {
            let p = local[i];
            verts[index] = p.x;
            verts[index + 1] = p.y;
            index += floatsPerVert;
        }
    }

    packToDynamicAtlas(comp, frame) {
        return;
        if (CC_TEST) return;

        if (!frame._original && cc.dynamicAtlasManager && frame._texture.packable) {
            let packedFrame = cc.dynamicAtlasManager.insertSpriteFrame(frame);
            //@ts-ignore
            if (packedFrame) {
                frame._setDynamicAtlasFrame(packedFrame);
            }
        }
        let material = comp._materials[0];
        if (!material) return;

        if (material.getProperty('texture') !== frame._texture) {
            // texture was packed to dynamic atlas, should update uvs
            comp._vertsDirty = true;
            comp._activateMaterial();
        }
    }
}
